package com.travelgroup.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.travelgroup.constant.NotificationConstant;
import com.travelgroup.domain.entity.*;
import com.travelgroup.enums.PayStatus;
import com.travelgroup.enums.PayType;
import com.travelgroup.enums.RefundStatus;
import com.travelgroup.exception.BusinessException;
import com.travelgroup.exception.R;
import com.travelgroup.mapper.PaymentOrderMapper;
import com.travelgroup.service.INotificationService;
import com.travelgroup.service.IPaymentOrderService;
import com.travelgroup.service.IRefundRecordService;
import com.travelgroup.utils.AliPayUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class PaymentOrderServiceImpl extends ServiceImpl<PaymentOrderMapper, PaymentOrder>
        implements IPaymentOrderService {
    @Resource
    private IRefundRecordService refundRecordService;
    @Resource
    private INotificationService notificationService;
    @Resource
    private AliPayUtil aliPayUtil;

    /**
     * 创建订单
     * @param group
     * @param user
     * @param amount
     * @param payType
     * @return
     */
    @Override
    @Transactional
    public R<PaymentOrder> createPaymentOrder(TourGroup group, User user, BigDecimal amount, PayType payType) {
        Long groupId = group.getId();
        Long userId = user.getId();
        // 检查是否存在订单
        Boolean isExit = this.lambdaQuery()
                .eq(PaymentOrder::getGroupId, groupId)
                .eq(PaymentOrder::getUserId, userId)
                .eq(PaymentOrder::getStatus, PayStatus.WAITING)
                .or(q -> q.eq(PaymentOrder::getStatus, PayStatus.SUCCESS))
                .count() > 0;
        if (isExit.equals(Boolean.TRUE)) {
            throw new BusinessException("已有待支付或已支付订单");
        }
        // 生成订单号
        String orderNo = generateOrderNo();

        // 创建订单信息
        PaymentOrder paymentOrder = new PaymentOrder();
        paymentOrder.setGroupId(groupId);
        paymentOrder.setUserId(userId);
        paymentOrder.setOrderNo(orderNo);
        paymentOrder.setStatus(PayStatus.WAITING);
        paymentOrder.setPaymentType(payType);
        paymentOrder.setAmount(amount);
        if (!this.save(paymentOrder)) {
            throw new BusinessException("订单创建失败");
        }
        return R.success("订单创建成功", paymentOrder);
    }

    /**
     * 检查用户是否已支付订单
     * @param groupId
     * @param userId
     * @return
     */
    @Override
    public boolean hasUserPaid(Long groupId, Long userId) {
        return this.lambdaQuery().eq(PaymentOrder::getGroupId, groupId)
                .eq(PaymentOrder::getUserId, userId)
                .eq(PaymentOrder::getStatus, PayStatus.SUCCESS)
                .exists();
    }

    /**
     * 获取支付二维码等信息
     * @param paymentOrder
     * @param groupTitle
     * @return
     */
    @Override
    public Map<String, Object> getPaymentInfo(PaymentOrder paymentOrder, String groupTitle) {
        // 获取订单号及费用，并检查订单是否处于等待状态
        String orderNo = paymentOrder.getOrderNo();
        BigDecimal amount = paymentOrder.getAmount();
        if (!PayStatus.WAITING.equals(paymentOrder.getStatus())) {
            throw new RuntimeException("订单状态异常");
        }

        // 根据支付类型调用不同的支付网关
        Map<String, Object> paymentInfo = new HashMap<>();
        switch (paymentOrder.getPaymentType()) {
            case PayType.ALIPAY: // 支付宝
                paymentInfo = aliPayUtil.pay(groupTitle, orderNo, amount.toString());
                break;
            case PayType.WECHAT: // 微信支付
                break;
            default:
                throw new RuntimeException("不支持的支付方式");
        }

        return paymentInfo;
    }


    /**
     * 根据订单号查询订单
     * @param orderNo
     * @return
     */
    @Override
    public R<PaymentOrder> getOrderByOrderNo(String orderNo) {
        PaymentOrder paymentOrder = this.lambdaQuery().eq(PaymentOrder::getOrderNo, orderNo).one();
        if (paymentOrder == null) {
            throw new BusinessException("订单号错误或不存在");
        }
        return R.success("订单号查询成功", paymentOrder);
    }

    /**
     * 生成订单号
     * @return
     */
    private String generateOrderNo() {
        return "P" + System.currentTimeMillis() + RandomUtil.randomNumbers(6);
    }

    /**
     * 生成退款号
     * @return
     */
    private String generateRefundNo() {
        return "R" + System.currentTimeMillis() + RandomUtil.randomNumbers(6);
    }

    /**
     * 处理回调信息
     * @param trade_no
     * @param orderNo
     * @param amount
     * @return
     */
    @Override
    @Transactional
    public boolean handlePaymentCallback(String trade_no, String orderNo, BigDecimal amount) {
        // 检查订单是否存在
        PaymentOrder paymentOrder = this.lambdaQuery().eq(PaymentOrder::getOrderNo, orderNo).one();
        if (paymentOrder == null) {
            throw new BusinessException("支付回调订单不存在");
        }
        // 检查订单金额是否正确
        if (paymentOrder.getAmount().compareTo(amount) != 0) {
            log.error("支付金额不一致，订单金额: {}, 回调金额: {}", paymentOrder.getAmount(), amount);
            throw new BusinessException("支付金额不一致");
        }

        // 修改订单状态
        paymentOrder.setTradeNo(trade_no);
        paymentOrder.setStatus(PayStatus.SUCCESS);
        paymentOrder.setPaymentTime(new Date());
        if (!this.updateById(paymentOrder)) {
            throw new BusinessException("订单信息更新失败");
        }

        return true;
    }

    /**
     * 取消支付
     * @param orderNo
     * @return
     */
    @Override
    public R<?> cancelPayment(String orderNo) {
        // 检查订单号是否存在
        if (orderNo == null  || orderNo.isBlank()) {
            throw new BusinessException("订单号为空");
        }

        // 获取订单信息
        PaymentOrder paymentOrder = this.lambdaQuery().eq(PaymentOrder::getOrderNo, orderNo).one();

        // 检查订单是否存在或已支付
        if (paymentOrder == null || paymentOrder.getStatus().equals(PayStatus.SUCCESS)) {
            throw new BusinessException("订单不存在或已支付");
        }

        // 删除订单
        if (!this.removeById(paymentOrder)) {
            throw new BusinessException("订单取消失败");
        }
        return R.success("订单取消成功", null);
    }

    /**
     * 退款
     * @param groupId
     * @param userId
     * @param reason
     * @return
     */
    @Override
    @Transactional
    public boolean refundByGroupAndUser(Long groupId, Long userId, String reason) {
        // 获取已支付订单
        PaymentOrder paymentOrder = this.lambdaQuery()
                .eq(PaymentOrder::getGroupId, groupId)
                .eq(PaymentOrder::getUserId, userId)
                .eq(PaymentOrder::getStatus, PayStatus.SUCCESS)
                .orderByDesc(PaymentOrder::getCreateTime)
                .last("limit 1")
                .one();
        if (paymentOrder == null) {
            log.warn("未找到该订单");
            return false;
        }

        // 生成订单号
        String refundNo = this.generateRefundNo();

        // 保存退款信息
        RefundRecord refundRecord = new RefundRecord();
        refundRecord.setRefundNo(refundNo);
        refundRecord.setRefundAmount(paymentOrder.getAmount());
        refundRecord.setRefundReason(reason);
        refundRecord.setOrderId(paymentOrder.getId());
        refundRecord.setRefundStatus(RefundStatus.APPLYING);
        if (!refundRecordService.save(refundRecord)) {
            throw new BusinessException("退款申请失败");
        }

        // 进行退款
        boolean refundResult = false;
        switch (paymentOrder.getPaymentType()) {
            case PayType.ALIPAY:
                // 支付宝
                refundResult = aliPayUtil.refund(paymentOrder);
                break;
            case PayType.WECHAT:
                // 微信支付

                break;
            default:
                throw new BusinessException("不支持的支付方式");
        }
        if (refundResult) {
            // 更新订单状态为已退款
            paymentOrder.setStatus(PayStatus.REFUND);
            if (!this.updateById(paymentOrder)) {
                throw new BusinessException("订单状态更新失败");
            }

            // 发送退款通知
            notificationService.sendRefundNotification(
                    paymentOrder.getUserId(),
                    NotificationConstant.REFUND_SUCCESS,
                    NotificationConstant.REFUND_SUCCESS_MESSAGE,
                    paymentOrder.getOrderNo(), paymentOrder.getAmount().toString());
        }
        return true;
    }

    /**
     * 批量退款
     * @param paymentOrders
     */
    @Transactional
    @Override
    public void processBatchRefund(List<PaymentOrder> paymentOrders) {
        // 为每一位成员分别进行退款
        List<RefundRecord> results = new ArrayList<>();
        for (PaymentOrder order : paymentOrders) {
            RefundRecord result = new RefundRecord();
            result.setOrderId(order.getId());
            result.setRefundNo(generateRefundNo());
            result.setRefundAmount(order.getAmount());
            result.setRefundReason("拼团旅行取消");
            try {
                log.info("处理退款，订单号: {}, 用户ID: {}, 金额: {}",
                        order.getOrderNo(), order.getUserId(), order.getAmount());

                // 执行退款
                boolean refundSuccess = aliPayUtil.refund(order);

                if (refundSuccess) {
                    throw new BusinessException("支付宝退款失败");
                }
                result.setRefundStatus(RefundStatus.SUCCESS);

                // 添加延迟，避免API限流
                if (paymentOrders.size() > 5) {
                    Thread.sleep(200);
                }

            } catch (Exception e) {
                log.error("处理退款异常，订单号: {}", order.getOrderNo(), e);
                result.setRefundStatus(RefundStatus.FAILURE);
            }
            results.add(result);
        }
        if (!refundRecordService.saveBatch(results)) {
            throw new BusinessException("退款记录存储失败");
        }
    }
}
